<?php
date_default_timezone_set('Europe/Paris');
$basePath = realpath(__DIR__ . '/../');
$baseDirectoryPath = realpath($basePath . '/../');
$importAfter = array();

spl_autoload_register(
    function($name){
        $file = realpath(getClassFile($name, '../'));
        if (isNullOrEmptyString($file) || !file_exists($file)) {
        	throw new Exception('Impossible to load class "'.$name.'" !');
        }
        require_once($file);
    }
);

/**
 * Returns the path to the class file
 * 
 * @param string $name
 * @param string $relPath
 * @return string
 */
function getClassFile($name, $relPath='../')
{
    global $basePath;
    $file = $basePath.'/'.$relPath.str_replace('\\', '/', $name).'.class.php' ;
    return $file;
}

/**
 * Returns the complete name for the class
 * 
 * @param string $path
 * @return string
 */
function getClassName(/*string*/ $path)
{
    $actionName = $path ;
    $pointPos = strrpos($path, '.');
    if ($pointPos !== false) {
        $actionName = '\\PsiFramework\\' . str_replace('.', '\\', $path);
    }
    return $actionName ;
}

/**
 * Import a class
 *
 * @param $class    string    the class to import with its package information
 */
function import(/*string*/ $class)
{
    global $basePath, $importAfter ;
    $path = $basePath . '/' . str_replace('.', '/', $class) . '.class.php';
    $file = realpath($path);
    if (isNullOrEmptyString($file) || !file_exists($file)) {
        throw new Exception('Impossible to load class "'.$class.'" ('.$path.') !');
    }
    require_once($file);

    if (array_key_exists($file, $importAfter)) {
        foreach ($importAfter[$file] as $subFile) {
            require_once($subFile);
        }
        unset($importAfter[$file]);
    }
}

/**
 * Import a class after the class loading
 *
 * @param $class    string    the class to import with its package information
 */
function importAfter(/*string*/ $class)
{
    global $basePath, $importAfter ;

    $file = realpath(
        $basePath . '/' . str_replace('.', '/', $class) . '.class.php'
    );
    $trace  = debug_backtrace();
    $parentFile = realpath($trace[0]['file']);

    if (!array_key_exists($parentFile, $importAfter)) {
        $importAfter[$parentFile] = array();
    }
    $importAfter[$parentFile][] = $file ;
}

/**
 * Import a library from the Lib directory
 *
 * @param $lib    string    the library to load
 */
function importLibrary(/*string*/ $lib)
{
    global $basePath ;
    $lib = realpath($basePath . '/' . $lib);
    require_once($lib);
}

/**
 * Import a file
 *
 * @param $file    string    the file to load
 */
function importFile(/*string*/ $file)
{
    global $basePath ;
    $file = realpath($basePath . '/' . $file);
    require($file);
}

/**
 * Returns the base directory path (where PsiFramework is installed)
 * @return string
 */
function getBaseDirectory()
{
    global $baseDirectoryPath;
    return $baseDirectoryPath;
}

/**
 * Gets the www directory
 *
 * @return the path to the www directory
 */
function getWwwDirectory()
{
	global $basePath ;
	return realpath($basePath . '/../www');
}

/**
 * Gets the applications directory
 *
 * @return the path to the applications directory
 */
function getApplicationsDirectory()
{
    global $basePath ;
    return realpath($basePath . '/Applications');
}

/**
 * Gets the plugins directory
 *
 * @return the path to the plugins directory
 */
function getPluginsDirectory()
{
    global $basePath ;
    return realpath($basePath . '/Plugins');
}

/**
 * Gets the application directory
 *
 * @return the path to the application directory
 */
function getApplicationDirectory(/*string*/ $applicationName)
{
    return getApplicationsDirectory() . '/' . $applicationName;
}

/**
 * Gets the plugin directory
 *
 * @return the path to the plugin directory
 */
function getPluginDirectory(/*string*/ $pluginName)
{
    return getPluginsDirectory() . '/' . $pluginName;
}

/**
 * Gets the application config directory
 *
 * @return the path to the application config directory
 */
function getApplicationConfigDirectory(/*string*/ $applicationName)
{
    return getApplicationDirectory($applicationName) . '/Config';
}

/**
 * Gets the plugin config directory
 *
 * @return the path to the plugin config directory
 */
function getPluginConfigDirectory(/*string*/ $pluginName)
{
    return getPluginDirectory($pluginName) . '/Config';
}

/**
 * Gets the config directory
 *
 * @return the path to the config directory
 */
function getConfigDirectory()
{
    global $basePath ;
    return realpath($basePath . '/Config');
}

/**
 * Gets the config file passed by its name
 *
 * @param $config    string    the config to retrieve
 * @return the path to the config file
 */
function getConfigFile(/*string*/ $config)
{
    return getConfigDirectory() . '/' . $config;
}

/**
 * Returns a canonical file path from a partial file path for the
 * active plugins
 *
 * @param string $partialFilePath
 * @return string
 */
function getPluginFilePath(/*string*/ $partialFilePath)
{
    $pluginNameEnd = strpos($partialFilePath, '}');
    $plugin = substr($partialFilePath, 1, $pluginNameEnd-1);
    $filePath = substr($partialFilePath, $pluginNameEnd+2);
    $file = getPluginDirectory($plugin) . '/' . $filePath ;
    return $file ;
}

/**
 * Returns a canonical file path from a partial file path for the
 * current application
 * 
 * @param string $partialFilePath
 * @return string
 */
function getApplicationFilePath(/*string*/ $partialFilePath)
{
    $applicationNameEnd = strpos($partialFilePath, ']');
    $application = substr($partialFilePath, 1, $applicationNameEnd-1);
    $filePath = substr($partialFilePath, $applicationNameEnd+2);
    $file = getApplicationDirectory($application) . '/' . $filePath ;
    return $file ;
}

/**
 * Returns a canonical file path from a partial file path
 * 
 * @param string $partialFilePath
 * @return string
 */
function getFile(/*string*/ $partialFilePath)
{
    $file = null ;
    if (startsWith($partialFilePath, '{') == true) {
        $file = getPluginFilePath($partialFilePath);
    } else if (startsWith($partialFilePath, '[') == true) {
        $file = getApplicationFilePath($partialFilePath);
    }

    if (is_null($file) || !file_exists($file)) $file = null ;

    return $file;
}

/**
 * Checks if a string is null or empty
 * 
 * @param string $string
 * @return boolean
 */
function isNullOrEmptyString(/*string*/ $string)
{
    return (is_null($string) || $string === '');
}

/**
 * Filters the string of all not wanted substrings ckeditor added
 * 
 * @param string $string
 * @return string
 */
function ckEditorFilter(/*string*/ $string)
{
    if (is_null($string)) {
        return null;
    }
    
    $string = str_replace(array("\r\n", "\n", "\r", "\t"), '', $string);
    $string = strip_tags($string, '<h1><h2><h3><h4><h5><h6><p><a><strong><u><em><ul><ol><li><img><br/><span>');
    
    return $string;
}

/**
 * Returns the string in a suitable file name format
 * 
 * @param string $name
 * @return string
 */
function getFormattedFileName($name)
{
    return str_ireplace(array(' ', '/', '\\', '\'', ':', ',', '|', '"', '&'), '_', $name);
}

/**
 * Replaces all non-ascii character by its ascii equivalent
 * 
 * @param string $str
 * @return string
 */
function psiNormalize($str)
{
    $invalid = array('Š'=>'S', 'š'=>'s', 'Đ'=>'Dj', 'đ'=>'dj', 'Ž'=>'Z', 'ž'=>'z',
    'Č'=>'C', 'č'=>'c', 'Ć'=>'C', 'ć'=>'c', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A',
    'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E', 'Ê'=>'E', 'Ë'=>'E',
    'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O',
    'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U', 'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y',
    'Þ'=>'B', 'ß'=>'Ss', 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a',
    'æ'=>'a', 'ç'=>'c', 'è'=>'e', 'é'=>'e', 'ê'=>'e',  'ë'=>'e', 'ì'=>'i', 'í'=>'i',
    'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o',
    'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y',  'ý'=>'y', 'þ'=>'b',
    'ÿ'=>'y', 'Ŕ'=>'R', 'ŕ'=>'r', "`" => "'", "´" => "'", "„" => ",", "`" => "'",
    "´" => "'", "“" => "\"", "”" => "\"", "´" => "'", "~" => "", "’" => "'");
    
    return str_replace(array_keys($invalid), array_values($invalid), $str);
}

/**
 * Replaces all sign of punctuation by a space
 * 
 * @param string $str
 * @return string
 */
function psiUnpuctuate($str)
{
    $unpunctuateTable = array('\\', '_', '.', ';', '?', '!', ',', ':', '/', '%', '*', '(', ')', '[', ']', '{', '}', '=' , '&', '@', '+', '#', '\'', '"', '°', '^', '|', '~', 'µ', '£', '$', 'ø', '<', '>', '²');
    return str_replace($unpunctuateTable, ' ', $str);
}

/**
 * Normalizes URLs
 * 
 * @param string $str
 * @return string
 */
function psiUrlNormalize($str)
{
    //transformation des caractères spéciaux
    $str = psiUnpuctuate(strtolower(psiNormalize($str)));

    /* suppression des espaces et car. non-alphanumériques remplacés par des tirets*/
    $str = preg_replace('#([^a-z0-9_])#', '-', trim($str));

    /* suppression des tirets multiples */
    $str = preg_replace('#([-]+)#', '-', $str);

    return $str;
}

/**
 * Replaces every space, slash, pipe, semicolon, etc by an underscore
 * 
 * @param string $name
 * @return mixed
 */
function removeSpecialChars($name)
{
    return str_ireplace(array(' ', '/', '\\', '\'', ':', ',', '|', '"', '&'), '_', $name);
}

/**
 * Removes every non ascii alphabetical or digit character
 * 
 * @param string $string
 * @return string
 */
function cleanString($string)
{
    return preg_replace(
        "/[^a-zA-Z0-9\s]/",
        "",
        strtolower(
            str_replace(
                ' ',
                '_',
                $string
            )
        )
    );
}

/**
 * Replaces non ascii characters by their ascii equivalent
 * Replaces quotes by the specified separator
 * 
 * @param string $string
 * @param bool $minimize
 * @param string $separator
 * @return string
 */
function formatStringForUrl($string, $minimize = false, $separator='-')
{
    $str = $string;
    $str = str_replace(
        array('Á', 'À', 'Â', 'Ä', 'Ã', 'Å', 'Ç', 'É', 'È', 'Ê', 'Ë', 'Í', 'Ï', 'Î', 'Ì', 'Ñ', 'Ó', 'Ò', 'Ô', 'Ö', 'Õ', 'Ú', 'Ù', 'Û', 'Ü', 'Ý', 'á', 'à', 'â', 'ä', 'ã', 'å', 'ç', 'é', 'è', 'ê', 'ë', 'í', 'ì', 'î', 'ï', 'ñ', 'ó', 'ò', 'ô', 'ö', 'õ', 'ú', 'ù', 'û', 'ü', 'ý', 'ÿ', ' ', '\'', '"'),
        array('A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'N', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', $separator, $separator, $separator),
        $string
    );
    
    if ($minimize) {
        $str = strtolower($str);
    }
        
    return $str;
}

/**
 * Format a telephone number
 * 
 * @param string $tel
 * @return string
 */
function formatTelephoneNumber($tel)
{
    //TODO deal with the locale
    return trim(chunk_split(preg_replace('/[^0-9]/', '', $tel), 2, ' '));    
}

/**
 * Returns the base name of a URI
 * 
 * @param string $uri
 * @return string
 */
function getUriBaseName(/*uri*/ $uri)
{
    $baseName = null;
    $lastSlash = strrpos($uri, '/', 8);
    
    if ($lastSlash !== false && $lastSlash>7) {
        $baseName = substr($uri, $lastSlash+1);
    }
    
    return $baseName;
}

/**
 * Returns true if the haystack starts with the needle substring
 * 
 * @param string $haystack
 * @param string $needle
 * @return boolean
 */
function startsWith(/*string*/ $haystack, /*string*/ $needle)
{
    $needleLength = strlen($needle);
    $haystackLength = strlen($haystack);
    if ($needleLength > $haystackLength) return false ;
    $stringStart = substr($haystack, 0, $needleLength);
    return $stringStart === $needle ;
}

/**
 * Returns true if the haystack ends with the needle substring
 * 
 * @param string $haystack
 * @param string $needle
 * @return boolean
 */
function endsWith(/*string*/ $haystack, /*string*/ $needle)
{
    $needleLength = strlen($needle);
    $haystackLength = strlen($haystack);
    if ($needleLength > $haystackLength) return false ;
    $stringEnd = substr(
        $haystack,
        $haystackLength-$needleLength,
        $needleLength
    );
    return $stringEnd === $needle ;
}

/**
 * Returns a string of nb spaces
 * 
 * @param int $nb
 * @return string
 */
function getBlankSpace(/*int*/ $nb=1)
{
    $bs = '';
    for ($i=0; $i<$nb; $i++) {
        $bs .= ' ';
    }
    return $bs;
}

/**
 * Returns the element identified by its tag name
 * 
 * @param DOMElement $element
 * @param string $tagName
 * @return DOMElement
 */
function getElementByTagName($element, $tagName)
{
    $returnEl = null;
    $returnEls = $element->getElementsByTagName($tagName);
    if (!is_null($returnEls)) {
        $returnEl = $returnEls->item(0);
    }
    return $returnEl;
}

/**
 * Returns the content of the element identified by its tag name
 * 
 * @param DOMElement $element
 * @param string $tagName
 * @return string
 */
function getContentByTagName($element, $tagName)
{
    $returnText = null;
    $returnEl = getElementByTagName($element, $tagName);
    if (!is_null($returnEl)) {
        $returnText = $returnEl->nodeValue;
    }
    return $returnText;
}

/**
 * Returns the string for XML purposes by replacing & characters
 * by the &amp; value
 * 
 * @param string $string
 * @return string
 */
function secureStringForXml($string)
{
    if (is_string($string)) {
        $str = str_replace('&', '&amp;', str_replace('&amp;', '&', $string));
        
        return $str;
    } else {
        return $string;
    }
}